"""
Repetition Code FEC implementation.

This is the improved FEC implementation using repetition coding.
Each original packet is sent multiple times to improve reliability.
"""

from typing import List, Optional, Dict, Any, TYPE_CHECKING
import time
import random
from ..logger_config import log_info, log_debug, log_warning, log_error, log_success, log_failure, log_progress, log_connection, log_media, log_stats

try:
    from .base import BaseFecCodec, FecConfig, FecPacket
except ImportError:
    from base import BaseFecCodec, FecConfig, FecPacket
# 延迟导入以避免循环依赖
if TYPE_CHECKING:
    try:
        from ..rtp import RtpPacket
    except ImportError:
        from rtp import RtpPacket

try:
    from ..utils import uint16_add
except ImportError:
    # 如果相对导入失败，尝试绝对导入
    try:
        from aiortc.utils import uint16_add
    except ImportError:
        # 如果绝对导入也失败，提供默认实现
        def uint16_add(a, b):
            return (a + b) & 0xFFFF


class RepetitionFec(BaseFecCodec):
    """重复码FEC实现（改进版本）"""
    
    def __init__(self, config: FecConfig):
        super().__init__(config)
        self.repetition_factor = config.repetition_factor
        self.adaptive_enabled = config.enable_adaptive
        self.network_quality_history = []
        self.max_history_size = 100
        
        # 改进的重复码参数
        self.adaptive_repetition = True
        self.min_repetition = 1
        self.max_repetition = 4
        self.quality_threshold = 0.95  # 网络质量阈值
    
    def encode(self, packets: List['RtpPacket']) -> List[FecPacket]:
        """重复码编码"""
        if len(packets) != self.config.k:
            raise ValueError(f"Expected {self.config.k} packets, got {len(packets)}")
        
        log_debug("RepetitionFec.encode: 开始编码 {packets_len} 个包", packets_len=len(packets))
        for i, packet in enumerate(packets):
            log_debug("包 {i}: 序列号={packet_sequence_number}, 负载长度={payload_length} bytes", i=i, packet_sequence_number=packet.sequence_number, payload_length=len(packet.payload))
        
        fec_packets = []
        total_repetitions = self.config.n // self.config.k
        
        for i, packet in enumerate(packets):
            # 确定重复次数（自适应）
            repetitions = self._get_adaptive_repetitions()
            log_debug("包 {i} 重复次数: {repetitions}", i=i, repetitions=repetitions)
            
            for j in range(repetitions):
                fec_packet = FecPacket(
                    fec_payload_id=self.sequence_number + i * total_repetitions + j,
                    repair_payload=packet.payload,
                    protected_sequence_numbers=[packet.sequence_number],
                    fec_type='repetition'
                )
                log_debug("创建FEC包: ID={fec_payload_id}, 负载长度={payload_length} bytes", fec_payload_id=fec_packet.fec_payload_id, payload_length=len(fec_packet.repair_payload))
                fec_packets.append(fec_packet)
        
        self.sequence_number += len(fec_packets)
        self.stats['encoded_packets'] += len(fec_packets)
        
        log_debug("RepetitionFec.encode: 生成了 {fec_packets_len} 个FEC包", fec_packets_len=len(fec_packets))
        return fec_packets
    
    def decode(self, original_packets: List[Optional['RtpPacket']], 
               fec_packets: List[FecPacket]) -> List[Optional['RtpPacket']]:
        """重复码解码"""
        self.stats['decoded_packets'] += 1
        
        # 创建结果列表
        result = original_packets.copy()
        
        # 按受保护的序列号分组FEC包
        fec_by_sequence = {}
        for fec_packet in fec_packets:
            for seq in fec_packet.protected_sequence_numbers:
                if seq not in fec_by_sequence:
                    fec_by_sequence[seq] = []
                fec_by_sequence[seq].append(fec_packet)
        
        # 尝试修复丢失的包
        for i, packet in enumerate(original_packets):
            if packet is None:
                # 找到对应的序列号
                if i < len(original_packets):
                    seq = self._get_sequence_number(i)
                    if seq in fec_by_sequence:
                        # 使用重复的FEC包修复
                        repaired_packet = self._repair_with_repetition(seq, fec_by_sequence[seq])
                        if repaired_packet:
                            result[i] = repaired_packet
                            self.stats['recovered_packets'] += 1
                        else:
                            self.stats['failed_recoveries'] += 1
        
        return result
    
    def can_repair(self, lost_packets: List[int], 
                   available_fec_packets: List[FecPacket]) -> bool:
        """检查是否可以用可用FEC包修复丢失的包"""
        if not available_fec_packets:
            return False
        
        # 按受保护的序列号分组
        fec_by_sequence = {}
        for fec_packet in available_fec_packets:
            for seq in fec_packet.protected_sequence_numbers:
                if seq not in fec_by_sequence:
                    fec_by_sequence[seq] = []
                fec_by_sequence[seq].append(fec_packet)
        
        # 检查每个丢失的包是否有足够的重复包
        for lost_seq in lost_packets:
            if lost_seq not in fec_by_sequence:
                return False
            
            # 需要至少一个重复包来修复
            if len(fec_by_sequence[lost_seq]) < 1:
                return False
        
        return True
    
    def _get_adaptive_repetitions(self) -> int:
        """获取自适应的重复次数"""
        if not self.adaptive_enabled:
            return self.repetition_factor
        
        # 基于网络质量历史调整重复次数
        if not self.network_quality_history:
            return self.repetition_factor
        
        recent_quality = sum(self.network_quality_history[-10:]) / min(10, len(self.network_quality_history))
        
        if recent_quality > self.quality_threshold:
            # 网络质量好，减少重复
            return max(self.min_repetition, self.repetition_factor - 1)
        elif recent_quality < 0.8:
            # 网络质量差，增加重复
            return min(self.max_repetition, self.repetition_factor + 1)
        else:
            return self.repetition_factor
    
    def _repair_with_repetition(self, sequence_number: int, 
                               fec_packets: List[FecPacket]) -> Optional['RtpPacket']:
        """使用重复包修复丢失的包"""
        if not fec_packets:
            return None
        
        # 选择第一个可用的FEC包
        fec_packet = fec_packets[0]
        
        # 创建修复的RTP包
        try:
            from ..rtp import RtpPacket
        except ImportError:
            from rtp import RtpPacket
        repaired_packet = RtpPacket(
            payload_type=96,  # 默认负载类型
            sequence_number=sequence_number,
            timestamp=int(fec_packet.timestamp * 90000),  # 转换为RTP时间戳
            payload=fec_packet.repair_payload
        )
        
        return repaired_packet
    
    def _get_sequence_number(self, index: int) -> int:
        """获取指定索引的序列号"""
        # 根据FEC包的受保护序列号来获取
        # 这里应该从FEC包的protected_sequence_numbers中获取
        return index
    
    def update_network_quality(self, quality: float):
        """更新网络质量信息"""
        if self.adaptive_enabled:
            self.network_quality_history.append(quality)
            if len(self.network_quality_history) > self.max_history_size:
                self.network_quality_history.pop(0)
    
    def get_adaptive_stats(self) -> Dict[str, Any]:
        """获取自适应统计信息"""
        return {
            'current_repetition_factor': self._get_adaptive_repetitions(),
            'network_quality_history': self.network_quality_history.copy(),
            'adaptive_enabled': self.adaptive_enabled
        }